package com.cq.hd.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.constant.RedisKeyConstant;
import com.cq.hd.common.entity.BusinessInfo;
import com.cq.hd.common.entity.UserInfo;
import com.cq.hd.common.entity.hf.HfBankPay;
import com.cq.hd.common.entity.hf.HfJsPay;
import com.cq.hd.common.entity.hf.HfTradeQuery;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.*;
import com.cq.hd.member.api.dto.*;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.member.config.LockUtils;
import com.cq.hd.member.mapper.*;
import com.cq.hd.member.po.*;
import com.cq.hd.member.service.TbBusinessService;
import com.cq.hd.member.service.TbMemberFeeConfigService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.system.api.HfApi;
import com.cq.hd.system.api.HfRequestRecordApi;
import com.cq.hd.system.api.dto.HfRequestRecordSaveDto;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员套餐配置表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2023-12-05
 */
@Slf4j
@Service
public class TbMemberFeeConfigServiceImpl extends ServiceImpl<TbMemberFeeConfigMapper, TbMemberFeeConfigPo> implements TbMemberFeeConfigService {

    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private TbBusinessService businessService;

    @Autowired
    private TbMemberFeeBillMapper memberFeeBillMapper;

    @Autowired
    private TbAppUserMapper appUserMapper;

    @Autowired
    private TbBankPayRecordMapper bankPayRecordMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private HfApi hfApi;

    @Autowired
    private HfRequestRecordApi hfRequestRecordApi;

    private void checkParams(TbMemberFeeConfigPo memberFeeConfigPo) {
        String memberName = memberFeeConfigPo.getMemberName();
        BigDecimal memberFee = memberFeeConfigPo.getMemberFee();
        BigDecimal originFee = memberFeeConfigPo.getOriginFee();
        Integer activeCount = memberFeeConfigPo.getActiveCount();
        Integer validMonth = memberFeeConfigPo.getValidMonth();
        Integer sort = memberFeeConfigPo.getSort();
        Integer memberType = memberFeeConfigPo.getMemberType();

        if (memberType == null || MemberTypeEnum.typeOf(memberType) == null) {
            Throw.isBusinessException("会员类型有误");
        }

        if (StringUtils.isBlank(memberName)) {
            Throw.isBusinessException("请输入套餐名称");
        }
        if (memberName.length() < 2) {
            Throw.isBusinessException("套餐名称最少输入2个字");
        }
        if (memberName.length() > 8) {
            Throw.isBusinessException("套餐名称最多输入8个字");
        }

        if (memberFee == null || memberFee.compareTo(new BigDecimal("0.01")) < 0) {
            Throw.isBusinessException("套餐费用不能少于0.01元");
        }
        if (memberFee.compareTo(new BigDecimal("99999999")) > 0) {
            Throw.isBusinessException("套餐费用必须小于99999999元");
        }

        if (originFee != null) {
            if (originFee.compareTo(new BigDecimal("1")) < 0) {
                Throw.isBusinessException("划线价格不能少于1元");
            }

            if (originFee.compareTo(new BigDecimal("99999999")) > 0) {
                Throw.isBusinessException("划线价格必须小于99999999元");
            }

            if (originFee.compareTo(memberFee) < 0) {
                Throw.isBusinessException("划线价格必须大于套餐费用");
            }
        }

        if (activeCount == null || activeCount <= 0) {
            Throw.isBusinessException("活动发布次数必须大于0次");
        }
        if (activeCount > 99999999) {
            Throw.isBusinessException("活动发布次数不能超过99999999次");
        }

        // 经纪人数，单活动商户数（一个活动最多引用几个商户的产品）。null表示不限制 判断
        Integer maxInviteAgentCount = memberFeeConfigPo.getMaxInviteAgentCount();
        if (maxInviteAgentCount != null) {
            if (maxInviteAgentCount < 1) {
                Throw.isBusinessException("经纪人数量不能小于1");
            }
            if (maxInviteAgentCount > 99999999) {
                Throw.isBusinessException("经纪人数量不能大于99999999");
            }
        }
        Integer singleActiveMerchantCount = memberFeeConfigPo.getSingleActiveMerchantCount();
        if (singleActiveMerchantCount != null) {
            if (singleActiveMerchantCount < 1) {
                Throw.isBusinessException("单活动商户数不能小于1");
            }
            if (singleActiveMerchantCount > 100) {
                Throw.isBusinessException("单活动商户数不能大于100");
            }
        }

        if (validMonth == null || validMonth <= 0) {
            Throw.isBusinessException("有效期必须大于0个月");
        }

        if (validMonth > 36) {
            Throw.isBusinessException("有效期不能超过36个月");
        }

        if (sort == null || sort <= 0) {
            Throw.isBusinessException("排序值必须大于0");
        }

        if (sort > 1000000) {
            Throw.isBusinessException("排序不能超过1000000");
        }

        Long id = 0L;
        if (memberFeeConfigPo.getId() != null) {
            id = memberFeeConfigPo.getId();
        }
        // 套餐名称
        Integer count = baseMapper.selectCount(new QueryWrapper<TbMemberFeeConfigPo>()
                .eq("del_state", 0)
                .ne("id", id)
                .eq("member_name", memberName));
        if (count != null && count > 0) {
            Throw.isBusinessException("套餐名称已存在");
        }
    }

    @Override
    public Long saveMemberFeeConfig(MemberFeeConfigSaveDto memberFeeConfigSaveDto) {
        TbMemberFeeConfigPo tbMemberFeeConfigPo = new TbMemberFeeConfigPo();
        BeanUtils.copyProperties(memberFeeConfigSaveDto, tbMemberFeeConfigPo);

        // 参数校验
        checkParams(tbMemberFeeConfigPo);

        // 显示状态(1-显示，2-隐藏)
        tbMemberFeeConfigPo.setShowState(1);
        tbMemberFeeConfigPo.setCreateTime(LocalDateTime.now());
        tbMemberFeeConfigPo.setUpdateTime(LocalDateTime.now());

        int insert = baseMapper.insert(tbMemberFeeConfigPo);
        if (insert == 0) {
            Throw.isBusinessException("保存会员套餐配置数据失败");
        }

        return tbMemberFeeConfigPo.getId();
    }

    @Override
    public Boolean updateMemberFeeConfig(MemberFeeConfigUpdateDto memberFeeConfigUpdateDto) {
        Long id = memberFeeConfigUpdateDto.getId();
        TbMemberFeeConfigPo tbMemberFeeConfigPo = baseMapper.selectById(id);
        if (tbMemberFeeConfigPo == null || tbMemberFeeConfigPo.getDelState() != 0) {
            Throw.isBusinessException("未找到会员套餐数据");
        }

        BeanUtils.copyProperties(memberFeeConfigUpdateDto, tbMemberFeeConfigPo);

        // 参数校验
        checkParams(tbMemberFeeConfigPo);

        tbMemberFeeConfigPo.setUpdateTime(LocalDateTime.now());
        int update = baseMapper.updateById(tbMemberFeeConfigPo);
        if (update == 0) {
            Throw.isBusinessException("更新会员套餐配置数据失败");
        }

        return true;
    }

    @Override
    public Page<MemberFeeConfigPageVo> pageMemberFeeConfig(MemberFeeConfigPageDto memberFeeConfigPageDto) {
        PageHelper.startPage(memberFeeConfigPageDto.getPageNum(), memberFeeConfigPageDto.getPageSize());
        List<MemberFeeConfigPageVo> memberFeeConfigPageVos = baseMapper.listMemberFeeConfig(memberFeeConfigPageDto);
        PageInfo<MemberFeeConfigPageVo> pageInfo = new PageInfo<>(memberFeeConfigPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public Page<AppMemberFeeConfigPageVo> pageAppMemberFeeConfig(AppMemberFeeConfigPageDto appMemberFeeConfigPageDto) {
        PageHelper.startPage(appMemberFeeConfigPageDto.getPageNum(), appMemberFeeConfigPageDto.getPageSize());
        List<AppMemberFeeConfigPageVo> appMemberFeeConfigPageVos = baseMapper.listAppMemberFeeConfig(appMemberFeeConfigPageDto);
        PageInfo<AppMemberFeeConfigPageVo> pageInfo = new PageInfo<>(appMemberFeeConfigPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public String createAppMemberFeeConfigOrder(AppMemberFeeConfigCreateDto appMemberFeeConfigCreateDto) {
        Long id = appMemberFeeConfigCreateDto.getId();
        if (id == null || id <= 0) {
            Throw.isBusinessException("请选择会员类型");
        }

        Integer payType = appMemberFeeConfigCreateDto.getPayType();
        if (payType == null || PayTypeEnum.typeOf(payType) == null) {
            Throw.isBusinessException("请选择支付方式");
        }

        Long userId = appMemberFeeConfigCreateDto.getUserId();
        Long businessId = appMemberFeeConfigCreateDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                // 如果不是商家，则返回空
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            businessId = tbBusinessPos.get(0).getId();
            appMemberFeeConfigCreateDto.setBusinessId(businessId);
        }

        TbAppUserPo appUserPo = appUserMapper.selectById(userId);
        if (appUserPo == null || StringUtils.isBlank(appUserPo.getOpenid())) {
            Throw.isBusinessException("请先授权");
        }

        // 对商家id加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "createAppMemberFeeConfigOrder:" + businessId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbMemberFeeConfigPo tbMemberFeeConfigPo = baseMapper.selectById(id);
            if (tbMemberFeeConfigPo == null || tbMemberFeeConfigPo.getDelState() != 0 || tbMemberFeeConfigPo.getShowState() != 1) {
                Throw.isBusinessException("未找到会员类型");
            }

            LocalDateTime now = LocalDateTime.now();
            String orderNo = NoUtils.getMemberFeeNo();

            TbMemberFeeBillPo tbMemberFeeBillPo = new TbMemberFeeBillPo();
            tbMemberFeeBillPo.setFeeConfigId(id);
            tbMemberFeeBillPo.setOrderBusinessId(businessId);
            tbMemberFeeBillPo.setOrderNo(orderNo);
            tbMemberFeeBillPo.setMemberName(tbMemberFeeConfigPo.getMemberName());
            tbMemberFeeBillPo.setMemberFee(tbMemberFeeConfigPo.getMemberFee());
            tbMemberFeeBillPo.setPayType(payType);
            tbMemberFeeBillPo.setPayState(PayStateEnum.WAIT.getValue());
            tbMemberFeeBillPo.setActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setRemainActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setValidMonth(tbMemberFeeConfigPo.getValidMonth());
            tbMemberFeeBillPo.setExpireCancelState(ExpireCancelStateEnum.NO_EXPIRE.getValue());
            tbMemberFeeBillPo.setMemberType(tbMemberFeeConfigPo.getMemberType());
            tbMemberFeeBillPo.setMaxInviteAgentCount(tbMemberFeeConfigPo.getMaxInviteAgentCount());
            tbMemberFeeBillPo.setSingleActiveMerchantCount(tbMemberFeeConfigPo.getSingleActiveMerchantCount());
            tbMemberFeeBillPo.setOrderTime(now);
            tbMemberFeeBillPo.setCreateTime(now);
            tbMemberFeeBillPo.setUpdateTime(now);
            int insert = memberFeeBillMapper.insert(tbMemberFeeBillPo);
            if (insert == 0) {
                Throw.isBusinessException("开通失败");
            }

            return orderNo;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    @Override
    public AppMemberFeeConfigPayVo payAppMemberFeeConfigOrder(AppMemberFeeConfigPayDto appMemberFeeConfigPayDto) {
        String orderNo = appMemberFeeConfigPayDto.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            Throw.isBusinessException("订单号不能为空");
        }

        TbBusinessPo tbBusinessPo;
        Long userId = appMemberFeeConfigPayDto.getUserId();
        Long businessId = appMemberFeeConfigPayDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            tbBusinessPo = tbBusinessPos.get(0);
            businessId = tbBusinessPo.getId();
            appMemberFeeConfigPayDto.setBusinessId(businessId);
        } else {
            tbBusinessPo = businessMapper.selectById(businessId);
            if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }
        }

        List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>().eq("del_state", 0)
                .eq("order_business_id", businessId)
                .eq("order_no", orderNo));
        if (CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
            Throw.isBusinessException("未找到订单数据");
        }

        TbMemberFeeBillPo tbMemberFeeBillPo = tbMemberFeeBillPos.get(0);
        if (!PayStateEnum.WAIT.getValue().equals(tbMemberFeeBillPo.getPayState())) {
            Throw.isBusinessException("订单已处理");
        }

        TbAppUserPo appUserPo = appUserMapper.selectById(userId);

        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
        String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);
        String timeExpire = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime.plusMinutes(30), "yyyyMMddHHmmss");

        HfJsPay hfJsPay = new HfJsPay();
        hfJsPay.setWxOpenid(appUserPo.getOpenid());
        hfJsPay.setReqSeqId(reqSeqId);
        hfJsPay.setReqDate(yyyyMMdd);
        hfJsPay.setTimeExpire(timeExpire);
        hfJsPay.setTransAmt(tbMemberFeeBillPo.getMemberFee().setScale(2, BigDecimal.ROUND_DOWN).toString());
        hfJsPay.setGoodsDesc(tbMemberFeeBillPo.getMemberName());
        hfJsPay.setAttach(PayAttachEnum.MEMBER_FEE_PAY.getName());
        JSONObject jsonObject = hfApi.jsPay(hfJsPay).unpack();
        if (jsonObject == null) {
            Throw.isBusinessException("开通失败");
        }

        JSONObject dataJSONObject = jsonObject.getJSONObject("data");
        String respCode = dataJSONObject.getString("resp_code");
        if (!"00000000".equals(respCode) && !"00000100".equals(respCode)) {
            Throw.isBusinessException("开通失败");
        }

        String payInfo = dataJSONObject.getString("pay_info");
//            String preOrderId = dataJSONObject.getString("pre_order_id");
        String partyOrderId = dataJSONObject.getString("party_order_id");
        if (StringUtils.isBlank(payInfo) || StringUtils.isBlank(partyOrderId)) {
            Throw.isBusinessException("开通失败");
        }

        tbMemberFeeBillPo.setPreOrderId(partyOrderId);
        tbMemberFeeBillPo.setHfReqSeqId(reqSeqId);
        tbMemberFeeBillPo.setHfReqDate(yyyyMMdd);
        tbMemberFeeBillPo.setPayState(PayStateEnum.PAYING.getValue());
        int update = memberFeeBillMapper.updateById(tbMemberFeeBillPo);
        if (update == 0) {
            Throw.isBusinessException("开通失败");
        }

        AppMemberFeeConfigPayVo appMemberFeeConfigPayVo = new AppMemberFeeConfigPayVo();
        appMemberFeeConfigPayVo.setOrderNo(payInfo);

        return appMemberFeeConfigPayVo;
    }

    @Override
    public Boolean jsPayCallback(JSONObject dataObj) {
        String subRespCode = dataObj.getString("sub_resp_code");
        String subRespDesc = dataObj.getString("sub_resp_desc");
        String hfMerchantNo = dataObj.getString("huifu_id");
        String reqDate = dataObj.getString("req_date");
        String reqSeqId = dataObj.getString("req_seq_id");
        // 交易状态	S：成功、F：失败；
        String transStat = dataObj.getString("trans_stat");

        // 添加汇付申请单记录（聚合支付下单回调，异步回调接口）
        HfRequestRecordSaveDto hfRequestRecordSaveDto = new HfRequestRecordSaveDto();
        hfRequestRecordSaveDto.setApplyType(HfRequestRecordApplyTypeEnum.WX_JS_ORDER_ASYNC.getValue());
        hfRequestRecordSaveDto.setRequestType(HfRequestRecordRequestTypeEnum.ASYNC.getValue());
        hfRequestRecordSaveDto.setApplyNo(PayAttachEnum.MEMBER_FEE_PAY.getName());
        hfRequestRecordSaveDto.setHuifuId(hfMerchantNo);
        hfRequestRecordSaveDto.setHfApplyNo(reqDate);
        hfRequestRecordSaveDto.setDataResult(JSON.toJSONString(dataObj));
        hfRequestRecordSaveDto.setReqSeqId(reqSeqId);
        hfRequestRecordSaveDto.setRespCode(subRespCode);
        hfRequestRecordSaveDto.setRespDesc(subRespDesc);
        hfRequestRecordSaveDto.setCreateTime(LocalDateTime.now());
        hfRequestRecordSaveDto.setUpdateTime(LocalDateTime.now());
        Boolean saveRequestRecordState = hfRequestRecordApi.saveRequestRecord(hfRequestRecordSaveDto).unpack();
        if (!saveRequestRecordState) {
            log.error("添加汇付申请单记录失败（聚合支付下单回调-开通会员，异步回调接口），hfRequestRecordSaveDto：{}", JSON.toJSONString(hfRequestRecordSaveDto));
        }

        List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>().eq("del_state", 0)
                .eq("hf_req_seq_id", reqSeqId).eq("hf_req_date", reqDate));
        if (CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
            log.error("jsPay回调失败，未找到开通会员订单数据，reqSeqId：{}，reqDate：{}", reqSeqId, reqDate);
            return false;
        }
        TbMemberFeeBillPo tbMemberFeeBillPo = tbMemberFeeBillPos.get(0);

        if ("00000000".equals(subRespCode) && "S".equals(transStat)) {
            if (!PayStateEnum.PAYING.getValue().equals(tbMemberFeeBillPo.getPayState())) {
                log.error("jsPay回调失败，开通会员订单非待支付状态，orderId:{}", tbMemberFeeBillPo.getId());
                return false;
            }

            // 如果交易成功，修改订单状态
            paySuccess(tbMemberFeeBillPo);

            return true;
        }

        if ("F".equals(transStat)) {
            tbMemberFeeBillPo.setPayState(PayStateEnum.FAIL.getValue());
            tbMemberFeeBillPo.setPayFailReason(dataObj.getString("bank_message"));
            tbMemberFeeBillPo.setUpdateTime(LocalDateTime.now());
            memberFeeBillMapper.updateById(tbMemberFeeBillPo);
        }

        return true;
    }

    @Override
    public Boolean queryOrderPay(AppMemberFeePayQueryDto appMemberFeePayQueryDto) {
        String orderNo = appMemberFeePayQueryDto.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            Throw.isBusinessException("订单号不能为空");
        }

        TbBusinessPo tbBusinessPo;
        Long userId = appMemberFeePayQueryDto.getUserId();
        Long businessId = appMemberFeePayQueryDto.getBusinessId();
        if (businessId == null || businessId <= 0) {
            if (userId == null || userId <= 0) {
                Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
            }

            // 根据userId查询商家id
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }

            tbBusinessPo = tbBusinessPos.get(0);
            businessId = tbBusinessPo.getId();
            appMemberFeePayQueryDto.setBusinessId(businessId);
        } else {
            tbBusinessPo = businessMapper.selectById(businessId);
            if (tbBusinessPo == null || tbBusinessPo.getDelState() != 0) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_ACCESS_DENIED);
            }
        }

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "queryMemberFeeOrderPay:" + orderNo);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>().eq("del_state", 0)
                    .eq("order_business_id", businessId)
                    .eq("order_no", orderNo));
            if (CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
                log.error("查单失败，未找到开通会员订单数据，orderNo：{}", orderNo);
                return false;
            }

            TbMemberFeeBillPo tbMemberFeeBillPo = tbMemberFeeBillPos.get(0);
            if (!OrderStateEnum.PAYING.getValue().equals(tbMemberFeeBillPo.getPayState())) {
                log.error("查单失败，开通会员订单不是支付中状态，orderNo：{}", orderNo);
                return true;
            }

            // 调用hf查单接口，避免临界点出现支付情况，如果查单状态是支付成功，则修改状态为待核销
            HfTradeQuery hfTradeQuery = new HfTradeQuery();
            hfTradeQuery.setOrgReqDate(tbMemberFeeBillPo.getHfReqDate());
            hfTradeQuery.setOrgReqSeqId(tbMemberFeeBillPo.getHfReqSeqId());
            JSONObject jsonObject = hfApi.tradeQuery(hfTradeQuery).unpack();
            if (jsonObject != null) {
                JSONObject dataJSONObject = jsonObject.getJSONObject("data");
                // 交易状态	P：处理中；S：成功；F：失败；I: 初始（初始状态很罕见，请联系汇付技术人员处理）；
                String transStat = dataJSONObject.getString("trans_stat");
                // NOTPAY，订单未支付
                String bankCode = dataJSONObject.getString("bank_code");
                log.info("查单成功，开通会员订单第三方交易状态：【{}】，orderNo：{}", transStat, orderNo);
                if ("S".equals(transStat)) {
                    paySuccess(tbMemberFeeBillPo);
                    return true;
                }

                if ("F".equals(transStat)) {
                    // 查单是支付失败，将支付中--》支付失败
                    tbMemberFeeBillPo.setPayState(PayStateEnum.FAIL.getValue());
                    tbMemberFeeBillPo.setPayFailReason("超时未支付");
                    tbMemberFeeBillPo.setUpdateTime(LocalDateTime.now());
                    memberFeeBillMapper.updateById(tbMemberFeeBillPo);
                }
            }
        } finally {
            LockUtils.unlock(lockKey);
        }

        return false;
    }

    public void paySuccess(TbMemberFeeBillPo tbMemberFeeBillPo) {
        Long orderBusinessId = tbMemberFeeBillPo.getOrderBusinessId();

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "memberFeePaySuccess:" + orderBusinessId);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbMemberFeeBillPo memberFeeBillPo = memberFeeBillMapper.selectById(tbMemberFeeBillPo.getId());
            if (!PayStateEnum.PAYING.getValue().equals(memberFeeBillPo.getPayState())) {
                log.error("开通会员订单支付成功处理，订单非支付中状态，orderId:{}", memberFeeBillPo.getId());
                return;
            }

            openMember(tbMemberFeeBillPo);
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    private void openMember(TbMemberFeeBillPo tbMemberFeeBillPo) {
        TbBusinessPo businessPo = businessMapper.selectById(tbMemberFeeBillPo.getOrderBusinessId());
        Long businessId = businessPo.getId();
        Long userId = businessPo.getUserId();

        // 计算最多可邀请经纪人数量(累计)，单活动商户数（一个活动最多引用几个商户的产品）
        calMaxAgentCount(businessPo, tbMemberFeeBillPo.getMaxInviteAgentCount());
        calMaxMerchantCount(businessPo, tbMemberFeeBillPo.getSingleActiveMerchantCount());

        // 获取会员到期时间，支付回调判断会员是否到期，应该以下单时间作为当前时间去判断，避免出现时间差问题
        LocalDateTime memberExpireTime = getMemberExpireTime(businessPo, tbMemberFeeBillPo.getValidMonth(), tbMemberFeeBillPo.getOrderTime());
        businessPo.setMemberExpireTime(memberExpireTime);

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 更新商家的到期时间
            int update = businessMapper.updateById(businessPo);
            if (update == 0) {
                log.error("会员开通失败，更新商家的到期时间失败，orderId:{}", tbMemberFeeBillPo.getId());
                Throw.isBusinessException("开通失败");
            }

            // 更新会员套餐充值流水时间
            tbMemberFeeBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
            tbMemberFeeBillPo.setPayTime(LocalDateTime.now());
            tbMemberFeeBillPo.setArriveTime(LocalDateTime.now());
            update = memberFeeBillMapper.updateById(tbMemberFeeBillPo);
            if (update == 0) {
                log.error("会员开通失败，更新会员套餐充值流水时间失败，orderId:{}", tbMemberFeeBillPo.getId());
                Throw.isBusinessException("开通失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<开通会员失败>事务异常回滚", e);
            Throw.isBusinessException("开通失败");
        }

        // 将最新的用户数据缓存Redis
        String userInfoRedis = redisUtil.get(String.format(RedisKeyConstant.USER_INFO_KEY, userId));
        if (!StringUtils.isNullOrEmpty(userInfoRedis)) {
            UserInfo userInfo = JSON.parseObject(userInfoRedis, UserInfo.class);
            BusinessInfo businessInfo = new BusinessInfo();
            BeanUtils.copyProperties(businessPo, businessInfo);
            userInfo.setBusinessInfo(businessInfo);

            redisUtil.set(String.format(RedisKeyConstant.USER_INFO_KEY, userId), JSON.toJSONString(userInfo), Constant.USER_LOGIN_TIMEOUT, TimeUnit.SECONDS);
        }
    }

    public LocalDateTime getMemberExpireTime(TbBusinessPo businessPo, Integer validMonth, LocalDateTime orderTime) {
        // 判断商家当前是否是会员，如果是会员，且未过期，则以当前商家过期时间+当前开通会员的有效期，更新为商家最新的过期时间
        // 如果不是会员，或会员已过期，则以支付时间+当前开通会员的有效期，更新为商家最新的过期时间
        LocalDateTime memberExpireTime = businessPo.getMemberExpireTime();
        if (memberExpireTime != null) {
            if (memberExpireTime.isAfter(orderTime)) {
                // 会员未过期
                memberExpireTime = LocalDateUtil.toLocalDateTime(
                        LocalDateUtil.toLocalDateToString(memberExpireTime.toLocalDate()
                                .plusMonths(validMonth), Constant.YYYY_MM_DD) + " 23:59:59", Constant.YYYY_MM_DD_HH_MM_SS);
            } else {
                // 会员已过期
                memberExpireTime = LocalDateUtil.toLocalDateTime(
                        LocalDateUtil.toLocalDateToString(orderTime.toLocalDate()
                                .plusMonths(validMonth), Constant.YYYY_MM_DD) + " 23:59:59", Constant.YYYY_MM_DD_HH_MM_SS);

                // 需要将之前开通支付成功的记录更新到期作废
                memberFeeBillMapper.updateExpireCancelState(ExpireCancelStateEnum.EXPIRE.getValue(),
                        PayStateEnum.SUCCESS.getValue(), businessPo.getId());
            }
        } else {
            // 当前商家不是会员
            memberExpireTime = LocalDateUtil.toLocalDateTime(
                    LocalDateUtil.toLocalDateToString(orderTime.toLocalDate()
                            .plusMonths(validMonth), Constant.YYYY_MM_DD) + " 23:59:59", Constant.YYYY_MM_DD_HH_MM_SS);
        }
        return memberExpireTime;
    }

    // 计算最多可邀请经纪人数量(累计)
    public void calMaxAgentCount(TbBusinessPo businessPo, Integer maxInviteAgentCount) {
        // 没设置，不限
        if (maxInviteAgentCount == null) {
            businessPo.setMaxInviteAgentCount(null);
            return;
        }

        // 已经购买的套餐里面，有不限的，那就是不限
        Long maxCount = memberFeeBillMapper.getMaxInviteAgentCount(businessPo.getId());
        if (maxCount != null && maxCount >= Constant.VERY_BIG_NUMBER) {
            businessPo.setMaxInviteAgentCount(null);
            return;
        }

        // 如果会员已经过期，直接按照最新的来
        LocalDateTime memberExpireTime = businessPo.getMemberExpireTime();
        LocalDateTime now = LocalDateTime.now();
        if (memberExpireTime == null || memberExpireTime.isBefore(now)) {
            businessPo.setMaxInviteAgentCount(maxInviteAgentCount);
            return;
        }

        // 商家当前的次数，比新的次数多，直接返回
        Integer curCount = businessPo.getMaxInviteAgentCount();
        if (curCount != null && curCount > maxInviteAgentCount) {
            return;
        }

        businessPo.setMaxInviteAgentCount(maxInviteAgentCount);
    }

    // 计算单活动商户数（一个活动最多引用几个商户的产品）
    public void calMaxMerchantCount(TbBusinessPo businessPo, Integer singleActiveMerchantCount) {
        // 没设置，不限
        if (singleActiveMerchantCount == null) {
            businessPo.setSingleActiveMerchantCount(null);
            return;
        }

        // 已经购买的套餐里面，有不限的，那就是不限
        Long maxCount = memberFeeBillMapper.getMaxSingleActiveMerchantCount(businessPo.getId());
        if (maxCount != null && maxCount >= Constant.VERY_BIG_NUMBER) {
            businessPo.setSingleActiveMerchantCount(null);
            return;
        }

        // 如果会员已经过期，直接按照最新的来
        LocalDateTime memberExpireTime = businessPo.getMemberExpireTime();
        LocalDateTime now = LocalDateTime.now();
        if (memberExpireTime == null || memberExpireTime.isBefore(now)) {
            businessPo.setSingleActiveMerchantCount(singleActiveMerchantCount);
            return;
        }

        // 商家当前的次数，比新的次数多，直接返回
        Integer curCount = businessPo.getSingleActiveMerchantCount();
        if (curCount != null && curCount > singleActiveMerchantCount) {
            return;
        }

        businessPo.setSingleActiveMerchantCount(singleActiveMerchantCount);
    }

    @Override
    public Boolean giveMemberFee(MemberFeeGiveDto memberFeeGiveDto) {
        Long businessId = memberFeeGiveDto.getBusinessId();
        Long memberFeeConfigId = memberFeeGiveDto.getMemberFeeConfigId();
        if (businessId == null || businessId <= 0) {
            Throw.isBusinessException("请选择赠送会员的商家");
        }

        if (memberFeeConfigId == null || memberFeeConfigId <= 0) {
            Throw.isBusinessException("请选择赠送会员的类型");
        }

        TbMemberFeeConfigPo tbMemberFeeConfigPo = baseMapper.selectById(memberFeeConfigId);
        if (tbMemberFeeConfigPo == null || tbMemberFeeConfigPo.getDelState() != 0 || tbMemberFeeConfigPo.getShowState() != 1) {
            Throw.isBusinessException("未找到会员类型");
        }

        TbBusinessPo businessPo = businessMapper.selectById(businessId);
        log.error("businessPo: {}", businessPo);
        if (businessPo == null || businessPo.getDelState() != 0) {
            Throw.isBusinessException("未找到商家数据");
        }
        Long userId = businessPo.getUserId();

        // 计算最多可邀请经纪人数量(累计)，单活动商户数（一个活动最多引用几个商户的产品）
        calMaxAgentCount(businessPo, tbMemberFeeConfigPo.getMaxInviteAgentCount());
        calMaxMerchantCount(businessPo, tbMemberFeeConfigPo.getSingleActiveMerchantCount());

        // 支付回调判断会员是否到期，应该以支付时间作为当前时间去判断，避免出现时间差问题
        LocalDateTime memberExpireTime = getMemberExpireTime(businessPo, tbMemberFeeConfigPo.getValidMonth(), LocalDateTime.now());
        businessPo.setMemberExpireTime(memberExpireTime);

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 更新商家的到期时间,最多可邀请经纪人数量(累计)，单活动商户数（一个活动最多引用几个商户的产品）
            int count = businessMapper.updateById(businessPo);
            if (count == 0) {
                Throw.isBusinessException("开通失败");
            }

            // 添加会员套餐流水数据
            TbMemberFeeBillPo tbMemberFeeBillPo = new TbMemberFeeBillPo();
            tbMemberFeeBillPo.setFeeConfigId(memberFeeConfigId);
            tbMemberFeeBillPo.setOrderBusinessId(businessId);
            tbMemberFeeBillPo.setOrderNo(NoUtils.getMemberFeeNo());
            tbMemberFeeBillPo.setMemberName(tbMemberFeeConfigPo.getMemberName());
            tbMemberFeeBillPo.setMemberFee(BigDecimal.ZERO);
            tbMemberFeeBillPo.setPayType(PayTypeEnum.GIVE.getValue());
            tbMemberFeeBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
            tbMemberFeeBillPo.setActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setRemainActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setValidMonth(tbMemberFeeConfigPo.getValidMonth());
            tbMemberFeeBillPo.setMemberType(tbMemberFeeConfigPo.getMemberType());
            tbMemberFeeBillPo.setMaxInviteAgentCount(tbMemberFeeConfigPo.getMaxInviteAgentCount());
            tbMemberFeeBillPo.setSingleActiveMerchantCount(tbMemberFeeConfigPo.getSingleActiveMerchantCount());
            tbMemberFeeBillPo.setReturnNo(memberFeeGiveDto.getAdminUserId() == null ? "0" : String.valueOf(memberFeeGiveDto.getAdminUserId()));
            tbMemberFeeBillPo.setOrderTime(LocalDateTime.now());
            tbMemberFeeBillPo.setPayTime(LocalDateTime.now());
            tbMemberFeeBillPo.setArriveTime(LocalDateTime.now());
            tbMemberFeeBillPo.setCreateTime(LocalDateTime.now());
            tbMemberFeeBillPo.setUpdateTime(LocalDateTime.now());
            tbMemberFeeBillPo.setExpireCancelState(ExpireCancelStateEnum.NO_EXPIRE.getValue());

            count = memberFeeBillMapper.insert(tbMemberFeeBillPo);
            if (count == 0) {
                log.error("赠送会员开通失败，添加会员套餐流水失败，orderId:{}", tbMemberFeeBillPo.getId());
                Throw.isBusinessException("开通失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<赠送会员失败>事务异常回滚", e);
            Throw.isBusinessException("开通失败");
        }

        // 将最新的用户数据缓存Redis
        String userInfoRedis = redisUtil.get(String.format(RedisKeyConstant.USER_INFO_KEY, userId));
        if (!StringUtils.isNullOrEmpty(userInfoRedis)) {
            UserInfo userInfo = JSON.parseObject(userInfoRedis, UserInfo.class);
            BusinessInfo businessInfo = new BusinessInfo();
            BeanUtils.copyProperties(businessPo, businessInfo);
            userInfo.setBusinessInfo(businessInfo);

            redisUtil.set(String.format(RedisKeyConstant.USER_INFO_KEY, userId), JSON.toJSONString(userInfo), Constant.USER_LOGIN_TIMEOUT, TimeUnit.SECONDS);
        }

        return true;
    }

    @Override
    public Boolean changeRights(MemberFeeChangeDto memberFeeChangeDto) {
        Long businessId = memberFeeChangeDto.getBusinessId();
        Integer activeCount = memberFeeChangeDto.getActiveCount();
        Integer maxInviteAgentCount = memberFeeChangeDto.getMaxInviteAgentCount();
        Integer singleActiveMerchantCount = memberFeeChangeDto.getSingleActiveMerchantCount();

        TbBusinessPo businessPo = businessMapper.selectById(businessId);
        if (businessPo == null || businessPo.getDelState() != 0) {
            Throw.isBusinessException("商家不存在");
        }
        Long userId = businessPo.getUserId();

        if (businessId == null || businessId <= 0) {
            Throw.isBusinessException("请选择修改权益的商家");
        }

        if (activeCount == null || activeCount <= 0) {
            Throw.isBusinessException("请输入发布次数，大于0的整数");
        }
        if (activeCount > 500) {
            Throw.isBusinessException("发布次数不能超过500");
        }

        // 免费次数
        Integer freeActiveCount = businessPo.getActiveCount();
        if (freeActiveCount == null || freeActiveCount < 0) {
            freeActiveCount = 0;
        }

        // 当前可用总次数：免费次数 + 会员套餐未使用次数 + 次卡未使用次数
        BusinessVo businessVo = businessService.getActiveCount(userId, businessId);
        Integer curTotalActiveCount = businessVo.getActiveCount();

        // 会员套餐未使用次数 + 次卡未使用次数
        int feeActiveCount = 0;
        if (curTotalActiveCount != null && curTotalActiveCount > 0) {
            feeActiveCount = curTotalActiveCount - freeActiveCount;
        }

        if (feeActiveCount > activeCount) {
            Throw.isBusinessException("发布次数不能小于会员套餐剩余次数：" + feeActiveCount);
        }
        // businessPo 里记录的是免费的次数，所以需要减掉套餐内的次数
        businessPo.setActiveCount(activeCount - feeActiveCount);

        if (maxInviteAgentCount != null) {
            if (maxInviteAgentCount <= 0) {
                Throw.isBusinessException("经纪人数不能小于1");
            }
            if (maxInviteAgentCount > 5000) {
                Throw.isBusinessException("经纪人数不能大于5000");
            }
        }
        businessPo.setMaxInviteAgentCount(maxInviteAgentCount);

        if (singleActiveMerchantCount != null) {
            if (singleActiveMerchantCount <= 0) {
                Throw.isBusinessException("单活动商户数不能小于1");
            }
            if (singleActiveMerchantCount > 100) {
                Throw.isBusinessException("单活动商户数不能大于100");
            }
        }
        businessPo.setSingleActiveMerchantCount(singleActiveMerchantCount);

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            int update = businessMapper.updateById(businessPo);
            if (update == 0) {
                Throw.isBusinessException("修改权益失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<修改权益失败>事务异常回滚", e);
            Throw.isBusinessException("修改权益失败");
        }

        log.info("修改商家权益：memberFeeChangeDto: {}, businessPo: {}", memberFeeChangeDto, businessPo);
        // 将最新的用户数据缓存Redis
        String userInfoRedis = redisUtil.get(String.format(RedisKeyConstant.USER_INFO_KEY, userId));
        if (!StringUtils.isNullOrEmpty(userInfoRedis)) {
            UserInfo userInfo = JSON.parseObject(userInfoRedis, UserInfo.class);
            BusinessInfo businessInfo = new BusinessInfo();
            BeanUtils.copyProperties(businessPo, businessInfo);
            userInfo.setBusinessInfo(businessInfo);

            redisUtil.set(String.format(RedisKeyConstant.USER_INFO_KEY, userId), JSON.toJSONString(userInfo), Constant.USER_LOGIN_TIMEOUT, TimeUnit.SECONDS);
        }

        return true;
    }

    @Override
    public MemberFeeConfigPageVo detailById(Long id) {
        TbMemberFeeConfigPo tbMemberFeeConfigPo = baseMapper.selectById(id);
        if (tbMemberFeeConfigPo != null && tbMemberFeeConfigPo.getShowState() == 1 && tbMemberFeeConfigPo.getDelState() == 0) {
            MemberFeeConfigPageVo memberFeeConfigPageVo = new MemberFeeConfigPageVo();
            BeanUtils.copyProperties(tbMemberFeeConfigPo, memberFeeConfigPageVo);
            return memberFeeConfigPageVo;
        }
        return null;
    }

    @Override
    public BankPayRechargeVo bankPayAdminMemberFeeConfigOrder(AdminBusinessMemberFeePayDto adminBusinessMemberFeePayDto) {
        Long id = adminBusinessMemberFeePayDto.getId();
        if (id == null || id <= 0) {
            Throw.isBusinessException("请选择会员类型");
        }

        TbMemberFeeConfigPo tbMemberFeeConfigPo = baseMapper.selectById(id);
        if (tbMemberFeeConfigPo == null || tbMemberFeeConfigPo.getShowState() != 1 || tbMemberFeeConfigPo.getDelState() != 0) {
            Throw.isBusinessException("未找到会员类型数据");
        }

        Long businessId = adminBusinessMemberFeePayDto.getBusinessId();
        TbBusinessPo businessPo = businessMapper.selectById(businessId);
        String hfMerchantNo = businessPo.getHfMerchantNo();
        if (StringUtils.isBlank(hfMerchantNo)) {
            log.error("网银开通会员失败，未正式入驻成功的商家不能使用网银支付，businessId：{}", businessId);
            Throw.isBusinessException("未正式入驻成功的商家不能使用网银支付");
        }

        BigDecimal rechargeAmt = tbMemberFeeConfigPo.getMemberFee();
        // 交易金额=输入充值金额+网银手续费
        BigDecimal tradeAmt = rechargeAmt.add(Constant.BANK_PAY_AMT);

        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
        String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);

        LocalDateTime timeExpireLocalDateTime = nowLocalDateTime.plusMinutes(120);
        String timeExpire = LocalDateUtil.toLocalDateTimeToString(timeExpireLocalDateTime, "yyyyMMddHHmmss");

        // 调用hf网银支付接口
        HfBankPay hfBankPay = new HfBankPay();
//        hfBankPay.setHuifuId(hfMerchantNo);
        hfBankPay.setReqSeqId(reqSeqId);
        hfBankPay.setReqDate(yyyyMMdd);
        hfBankPay.setTimeExpire(timeExpire);
        hfBankPay.setTransAmt(tradeAmt.toString());
        hfBankPay.setGoodsDesc("火动会员-" + tbMemberFeeConfigPo.getMemberName());
        hfBankPay.setRequestIp(adminBusinessMemberFeePayDto.getRequestIp());
        hfBankPay.setRemark(String.valueOf(BankPayTradeTypeEnum.MERCHANT_FEE.getValue()));
        JSONObject jsonObject = hfApi.bankPay(hfBankPay).unpack();
        if (jsonObject == null) {
            log.error("网银开通会员失败，调用hf网银支付接口失败，businessId：{}", businessId);
            Throw.isBusinessException("开通失败，请联系客服");
        }

        JSONObject dataJSONObject = jsonObject.getJSONObject("data");
        String respCode = dataJSONObject.getString("resp_code");
        String respDesc = dataJSONObject.getString("resp_desc");
        if (!"00000000".equals(respCode)) {
            Throw.isBusinessException(respDesc);
        }

        String formUrl = dataJSONObject.getString("form_url");
        // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
        String transStat = dataJSONObject.getString("trans_stat");

        if (StringUtils.isBlank(formUrl)) {
            log.error("网银开通会员失败，获取网银跳转链接数据为空，businessId：{}，memberFeeConfigId：{}", businessId, id);
            Throw.isBusinessException("开通失败，请联系客服");
        }

        int tradeState = BankPayTradeStateEnum.WAIT_PAY.getValue();
        if ("P".equals(transStat)) {
            tradeState = BankPayTradeStateEnum.PROCESSING.getValue();
        } else if ("S".equals(transStat)) {
            tradeState = BankPayTradeStateEnum.SUCCESS.getValue();
        } else if ("F".equals(transStat)) {
            tradeState = BankPayTradeStateEnum.FAIL.getValue();
        }

        LocalDateTime now = LocalDateTime.now();
        String bankPayOrderNo = NoUtils.getBankPayOrderNo();

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 添加开通会员流水和网银支付记录
            TbMemberFeeBillPo tbMemberFeeBillPo = new TbMemberFeeBillPo();
            tbMemberFeeBillPo.setFeeConfigId(id);
            tbMemberFeeBillPo.setOrderBusinessId(businessId);
            tbMemberFeeBillPo.setOrderNo(NoUtils.getMemberFeeNo());
            tbMemberFeeBillPo.setMemberName(tbMemberFeeConfigPo.getMemberName());
            tbMemberFeeBillPo.setMemberFee(tbMemberFeeConfigPo.getMemberFee());
            tbMemberFeeBillPo.setPayType(PayTypeEnum.BANK.getValue());
            tbMemberFeeBillPo.setPayState(PayStateEnum.WAIT.getValue());
            tbMemberFeeBillPo.setActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setRemainActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setValidMonth(tbMemberFeeConfigPo.getValidMonth());
            tbMemberFeeBillPo.setMemberType(tbMemberFeeBillPo.getMemberType());
            tbMemberFeeBillPo.setActiveCount(tbMemberFeeConfigPo.getActiveCount());
            tbMemberFeeBillPo.setSingleActiveMerchantCount(tbMemberFeeConfigPo.getSingleActiveMerchantCount());
            tbMemberFeeBillPo.setExpireCancelState(ExpireCancelStateEnum.NO_EXPIRE.getValue());
            tbMemberFeeBillPo.setOrderTime(now);
            tbMemberFeeBillPo.setCreateTime(now);
            tbMemberFeeBillPo.setUpdateTime(now);
            int insert = memberFeeBillMapper.insert(tbMemberFeeBillPo);
            if (insert == 0) {
                log.error("网银开通会员失败，添加会员开通记录失败，businessId：{}", businessId);
                Throw.isBusinessException("开通失败，请联系客服");
            }

            TbBankPayRecordPo tbBankPayRecordPo = new TbBankPayRecordPo();
            tbBankPayRecordPo.setBusinessId(businessId);
            tbBankPayRecordPo.setUserId(adminBusinessMemberFeePayDto.getUserId());
            tbBankPayRecordPo.setOrderNo(bankPayOrderNo);
            tbBankPayRecordPo.setTradeType(BankPayTradeTypeEnum.MERCHANT_FEE.getValue());
            tbBankPayRecordPo.setRelationTradeNo(tbMemberFeeBillPo.getOrderNo());
            tbBankPayRecordPo.setHfId(hfMerchantNo);
            tbBankPayRecordPo.setReqSeqId(reqSeqId);
            tbBankPayRecordPo.setReqDate(yyyyMMdd);
            tbBankPayRecordPo.setTimeExpire(timeExpire);
            tbBankPayRecordPo.setRequestIp(adminBusinessMemberFeePayDto.getRequestIp());
            tbBankPayRecordPo.setTradeAmt(tradeAmt);
            tbBankPayRecordPo.setFeeAmt(Constant.BANK_PAY_AMT);
            tbBankPayRecordPo.setReceiveAmt(rechargeAmt);
            tbBankPayRecordPo.setTradeState(tradeState);
            tbBankPayRecordPo.setAcctState(BankPayTradeStateEnum.WAIT_PAY.getValue());
            tbBankPayRecordPo.setTradeTime(now);
            tbBankPayRecordPo.setCreateTime(now);
            tbBankPayRecordPo.setUpdateTime(now);
            insert = bankPayRecordMapper.insert(tbBankPayRecordPo);
            if (insert == 0) {
                log.error("网银开通会员失败，添加网银支付记录失败，businessId：{}", businessId);
                Throw.isBusinessException("开通失败，请联系客服");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<网银支付开通会员>事务异常回滚", e);
        }

        BankPayRechargeVo bankPayRechargeVo = new BankPayRechargeVo();
        bankPayRechargeVo.setFromUrl(formUrl);
        bankPayRechargeVo.setOrderNo(bankPayOrderNo);

        return bankPayRechargeVo;
    }

    @Override
    public BankPayQueryVo queryBankPayOrder(BankPayQueryDto bankPayQueryDto) {
        String orderNo = bankPayQueryDto.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            Throw.isBusinessException("订单号不能为空");
        }

        List<TbBankPayRecordPo> tbBankPayRecordPos = bankPayRecordMapper.selectList(new QueryWrapper<TbBankPayRecordPo>().eq("del_state", 0)
                .eq("order_no", orderNo)
                .orderByDesc("create_time"));
        if (CollectionUtils.isEmpty(tbBankPayRecordPos)) {
            log.error("查单失败，未找到网银支付订单数据，orderNo：{}", orderNo);
            Throw.isBusinessException("未找到订单");
        }

        TbBankPayRecordPo tbBankPayRecordPo = tbBankPayRecordPos.get(0);
        // 交易状态(1-待支付，2-处理中，3-成功，4-失败)
        Integer tradeState = tbBankPayRecordPo.getTradeState();

        BankPayQueryVo bankPayQueryVo = new BankPayQueryVo();
        bankPayQueryVo.setTradeState(tradeState);

        if (BankPayTradeStateEnum.SUCCESS.getValue().equals(tradeState) || BankPayTradeStateEnum.FAIL.getValue().equals(tradeState)) {
            return bankPayQueryVo;
        }

        // 如果是待支付/处理中交易状态，需要调用hf接口做查单处理
        HfTradeQuery hfTradeQuery = new HfTradeQuery();
        hfTradeQuery.setHfMerchantNo(tbBankPayRecordPo.getHfId());
        hfTradeQuery.setOrgReqDate(tbBankPayRecordPo.getReqDate());
        hfTradeQuery.setOrgReqSeqId(tbBankPayRecordPo.getReqSeqId());
        JSONObject jsonObject = hfApi.bankPayQuery(hfTradeQuery).unpack();
        if (jsonObject != null) {
            JSONObject dataJSONObject = jsonObject.getJSONObject("data");
            // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
            String transStat = dataJSONObject.getString("trans_stat");
            log.info("查网银支付订单成功，订单第三方交易状态：【{}】，orderNo：{}", transStat, orderNo);

            if ("S".equals(transStat)) {
                // 支付成功，更新网银支付记录状态，增加补贴金，增加补贴金流水数据
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.SUCCESS.getValue());
                tbBankPayRecordPo.setCallbackTime(LocalDateTime.now());
                tbBankPayRecordPo.setUpdateTime(LocalDateTime.now());
                // hf全局流水号
                tbBankPayRecordPo.setHfSeqId(dataJSONObject.getString("org_hf_seq_id"));

                JSONObject bankExtendParamData = dataJSONObject.getJSONObject("bank_extend_param_data");
                if (bankExtendParamData != null) {
                    // 付款方银行号
                    tbBankPayRecordPo.setBankId(bankExtendParamData.getString("bank_id"));
                    // 付款方银行账户
                    tbBankPayRecordPo.setPyerAcctId(bankExtendParamData.getString("pyer_acct_id"));
                    // 付款方银行账户名
                    tbBankPayRecordPo.setPyerAcctNm(bankExtendParamData.getString("pyer_acct_nm"));
                }

                // 更新网银支付记录状态，更新商家到期时间，更新会员套餐充值流水时间
                bankPaySuccess(tbBankPayRecordPo);
                bankPayQueryVo.setTradeState(BankPayTradeStateEnum.SUCCESS.getValue());
            } else if ("F".equals(transStat)) {
                // 支付失败，更新网银支付记录状态和失败原因
                String bankDesc = dataJSONObject.getString("bank_desc");

                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
                tbBankPayRecordPo.setFailReason(bankDesc);
                tbBankPayRecordPo.setHfFailReason(bankDesc);
                tbBankPayRecordPo.setCallbackTime(LocalDateTime.now());
                tbBankPayRecordPo.setUpdateTime(LocalDateTime.now());
                bankPayRecordMapper.updateById(tbBankPayRecordPo);

                bankPayQueryVo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
            } else if ("P".equals(transStat)) {
                // 处理中，更新网银支付记录状态
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.PROCESSING.getValue());
                tbBankPayRecordPo.setUpdateTime(LocalDateTime.now());
                bankPayRecordMapper.updateById(tbBankPayRecordPo);

                bankPayQueryVo.setTradeState(BankPayTradeStateEnum.PROCESSING.getValue());
            }
        }

        return bankPayQueryVo;
    }

    private void bankPaySuccess(TbBankPayRecordPo tbBankPayRecordPo) {
        // 根据订单号查询网银待支付的开卡记录
        List<TbMemberFeeBillPo> tbMemberFeeBillPos = memberFeeBillMapper.selectList(new QueryWrapper<TbMemberFeeBillPo>()
                .eq("del_state", 0)
                .eq("pay_type", PayTypeEnum.BANK.getValue())
                .eq("order_no", tbBankPayRecordPo.getOrderNo())
                .eq("pay_state", PayStateEnum.WAIT.getValue())
                .orderByDesc("order_time"));

        if (CollectionUtils.isEmpty(tbMemberFeeBillPos)) {
            // 更新网银支付记录状态
            int count = bankPayRecordMapper.updateById(tbBankPayRecordPo);
            if (count == 0) {
                log.error("网银支付会员开通失败，更新网银支付记录状态失败，bankPayRecordId:{}", tbBankPayRecordPo.getId());
                Throw.isBusinessException("更新网银支付记录失败");
            }

            return;
        }

        TbMemberFeeBillPo tbMemberFeeBillPo = tbMemberFeeBillPos.get(0);
        TbBusinessPo businessPo = businessMapper.selectById(tbMemberFeeBillPo.getOrderBusinessId());

        // 计算最多可邀请经纪人数量(累计)，单活动商户数（一个活动最多引用几个商户的产品）
        calMaxAgentCount(businessPo, tbMemberFeeBillPo.getMaxInviteAgentCount());
        calMaxMerchantCount(businessPo, tbMemberFeeBillPo.getSingleActiveMerchantCount());

        // 获取会员到期时间，支付回调判断会员是否到期，应该以下单时间作为当前时间去判断，避免出现时间差问题
        LocalDateTime memberExpireTime = getMemberExpireTime(businessPo, tbMemberFeeBillPo.getValidMonth(), tbMemberFeeBillPo.getOrderTime());
        businessPo.setMemberExpireTime(memberExpireTime);

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 更新商家的到期时间
            int update = businessMapper.updateById(businessPo);
            if (update == 0) {
                log.error("网银支付会员开通失败，更新商家的到期时间失败，orderId:{}", tbMemberFeeBillPo.getId());
                Throw.isBusinessException("开通失败");
            }

            // 更新会员套餐充值流水时间
            tbMemberFeeBillPo.setPayState(PayStateEnum.SUCCESS.getValue());
            tbMemberFeeBillPo.setPayTime(LocalDateTime.now());
            tbMemberFeeBillPo.setArriveTime(LocalDateTime.now());
            update = memberFeeBillMapper.updateById(tbMemberFeeBillPo);
            if (update == 0) {
                log.error("网银支付会员开通失败，更新会员套餐充值流水时间失败，orderId:{}", tbMemberFeeBillPo.getId());
                Throw.isBusinessException("开通失败");
            }

            // 更新网银支付记录状态
            int count = bankPayRecordMapper.updateById(tbBankPayRecordPo);
            if (count == 0) {
                Throw.isBusinessException("更新网银支付记录失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<网银支付开通会员>事务异常回滚", e);
        }
    }

    @Override
    public Boolean bankPayCallback(JSONObject dataObj) {
        String subRespCode = dataObj.getString("sub_resp_code");
        String subRespDesc = dataObj.getString("sub_resp_desc");
        String hfMerchantNo = dataObj.getString("huifu_id");
        String reqDate = dataObj.getString("req_date");
        String reqSeqId = dataObj.getString("req_seq_id");
        //   // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
        String transStat = dataObj.getString("trans_stat");
        //   // P：处理中，S：成功，F：失败，I：初始化（停留在操作页面没选银行支付会是I状态）；
        String acctStat = dataObj.getString("acct_stat");
        // 通知类型	1：通道通知，2：财务通知；
        String notifyType = dataObj.getString("notify_type");

        // 根据reqSeqId+reqDate查询网银支付记录
        List<TbBankPayRecordPo> tbBankPayRecordPos = bankPayRecordMapper.selectList(new QueryWrapper<TbBankPayRecordPo>().eq("del_state", 0)
                .eq("trade_type", BankPayTradeTypeEnum.MERCHANT_FEE.getValue())
                .eq("req_date", reqDate)
                .eq("req_seq_id", reqSeqId).orderByDesc("create_time"));
        if (CollectionUtils.isEmpty(tbBankPayRecordPos)) {
            log.error("网银开通会员回调, 未找到网银支付记录数据, reqSeqId:{}, reqDate:{}", reqSeqId, reqDate);
            return true;
        }

        TbBankPayRecordPo tbBankPayRecordPo = tbBankPayRecordPos.get(0);

        // 添加汇付申请单记录（网银支付下单回调，异步回调接口）
        HfRequestRecordSaveDto hfRequestRecordSaveDto = new HfRequestRecordSaveDto();
        hfRequestRecordSaveDto.setApplyType(HfRequestRecordApplyTypeEnum.BANK_PAY_ASYNC.getValue());
        hfRequestRecordSaveDto.setRequestType(HfRequestRecordRequestTypeEnum.ASYNC.getValue());
        hfRequestRecordSaveDto.setApplyNo(PayAttachEnum.MEMBER_FEE_PAY.getName());
        hfRequestRecordSaveDto.setHuifuId(hfMerchantNo);
        hfRequestRecordSaveDto.setHfApplyNo(tbBankPayRecordPo.getOrderNo());
        hfRequestRecordSaveDto.setDataResult(JSON.toJSONString(dataObj));
        hfRequestRecordSaveDto.setReqSeqId(reqSeqId);
        hfRequestRecordSaveDto.setRespCode(subRespCode);
        hfRequestRecordSaveDto.setRespDesc(subRespDesc);
        hfRequestRecordSaveDto.setCreateTime(LocalDateTime.now());
        hfRequestRecordSaveDto.setUpdateTime(LocalDateTime.now());
        Boolean saveRequestRecordState = hfRequestRecordApi.saveRequestRecord(hfRequestRecordSaveDto).unpack();
        if (!saveRequestRecordState) {
            log.error("添加汇付申请单记录失败（网银支付下单回调-开通会员，异步回调接口），hfRequestRecordSaveDto：{}", JSON.toJSONString(hfRequestRecordSaveDto));
        }

        if (BankPayTradeStateEnum.FAIL.getValue().equals(tbBankPayRecordPo.getTradeState())
                || BankPayTradeStateEnum.SUCCESS.getValue().equals(tbBankPayRecordPo.getTradeState())) {
            log.error("网银开通会员回调, 订单已处理, reqSeqId:{}, reqDate:{}", reqSeqId, reqDate);
            return true;
        }

        if ("00000000".equals(subRespCode)) {
            if ("S".equals(transStat)) {
                // 交易成功
                if ("S".equals(acctStat)) {
                    // 入账成功
                    bankPaySuccess(tbBankPayRecordPo);
                } else {
                    // 只更新财务状态,但不更新交易状态,也不增加资金
                    if ("P".equals(acctStat)) {
                        bankPayRecordMapper.updateAcctState(tbBankPayRecordPo.getId(), BankPayTradeStateEnum.PROCESSING.getValue());
                    } else if ("F".equals(acctStat)) {
                        bankPayRecordMapper.updateAcctState(tbBankPayRecordPo.getId(), BankPayTradeStateEnum.FAIL.getValue());
                    }
                }
            } else if ("F".equals(transStat)) {
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
                tbBankPayRecordPo.setFailReason(dataObj.getString("bank_desc"));
                tbBankPayRecordPo.setHfFailReason(JSON.toJSONString(dataObj));
                bankPayRecordMapper.updateById(tbBankPayRecordPo);
            }
        } else {
            if ("F".equals(transStat)) {
                tbBankPayRecordPo.setTradeState(BankPayTradeStateEnum.FAIL.getValue());
                tbBankPayRecordPo.setFailReason(dataObj.getString("bank_desc"));
                tbBankPayRecordPo.setHfFailReason(JSON.toJSONString(dataObj));
                bankPayRecordMapper.updateById(tbBankPayRecordPo);
            }
        }

        return true;
    }
}
